package	model.code;

import editor.PwnIDE;
import model.code.line.SingleLine;

import java.io.BufferedReader;
import java.io.File;
import java.io.IOException;
import java.io.InputStreamReader;

/**
 * This class is for representing an option for compiling.
 *
 * @author Neil Dickson
 */
public class CompileOption extends Rowable {
	/**
	 * This is because Java can't do virtual static functions
	 */
	public static final CompileOption	DUMMY = new CompileOption("","",null,0);

	public static final int	TEXT_INDEX		= 0;
	public static final int	COMMAND_INDEX	= 1;
	public static final int	NUM_STRINGS		= 2;

	public CompileOption(String text, String command,CodeFileChunk parent,int row) {
		super(NUM_STRINGS,parent,CodeFileChunk.LOCATION_NOWHERE,row);
		strings[TEXT_INDEX] = new SingleLine(text.toCharArray(),parent,CodeFileChunk.LOCATION_NOWHERE,TEXT_INDEX+(row<<16));
		strings[COMMAND_INDEX] = new SingleLine(command.toCharArray(),parent,CodeFileChunk.LOCATION_NOWHERE,COMMAND_INDEX+(row<<16));
	}

	public String execute(String thisFilePath) throws IOException {
		File file = new File(thisFilePath);
		StringBuffer buf = new StringBuffer();
		Process process = Runtime.getRuntime().exec(translate(getCommand().toString(),file),null,file.getParentFile());
		BufferedReader output = new BufferedReader(new InputStreamReader(process.getInputStream()));
		BufferedReader errors = new BufferedReader(new InputStreamReader(process.getErrorStream()));
		String line;
		while ((line = output.readLine())!=null || (line = errors.readLine())!=null) {
			buf.append(line).append('\n');
		}
		int exitCode = -1234567890;
		try {
			exitCode = process.waitFor();
		}
		catch (InterruptedException e) {
			// Do nothing, because this doesn't matter
		}
		if (exitCode==0) {
			return buf.toString()+"\nOperation completed successfully.";
		}
		return buf.toString()+"\nOperation completed with errors.";
	}

	/**
	 * Replaces path variables in command and returns expanded command string
	 * @param command the command string, possibly containing variables denoted by $VarName$
	 * @param file the path of the current file
	 * @return expanded command string
	 */
	public static String translate(String command,File file) {
		int index;
		int prevIndex = 0;
		while ((index = command.indexOf('$',prevIndex))>=prevIndex) {
			int endIndex = command.indexOf('$',index+1);
			if (endIndex>=0) {
				String varName = command.substring(index+1,endIndex);
				if (varName.equals("this")) {
					command = command.substring(0,index)+"\""+file.getName()+"\""+command.substring(endIndex+1);
					prevIndex = index+file.getName().length()+2;
				}
				else if (PwnIDE.settings!=null && PwnIDE.settings.containsKey(varName+"Var")) {
					String text = PwnIDE.settings.get(varName+"Var");
					command = command.substring(0,index)+text+command.substring(endIndex+1);
					prevIndex = index+text.length();
				}
				else {
					prevIndex = endIndex+1;
				}
			}
			else {
				break;
			}
		}
		return command;
	}

	public SingleLine getText() {
		return strings[TEXT_INDEX];
	}
	public SingleLine getCommand() {
		return strings[COMMAND_INDEX];
	}

	public CompileOption copy(CodeFileChunk parent,int row) {
		return new CompileOption(getText().toString(),getCommand().toString(),parent,row);
	}
}
